package com.esdk.utils;

import com.esdk.esdk;
import com.esdk.interfaces.Callback;
import com.esdk.interfaces.Func;
import com.esdk.interfaces.FuncNoArg;
import lombok.NonNull;
import org.nutz.castor.Castors;

import java.io.Serializable;
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
import java.math.BigDecimal;
import java.sql.Time;
import java.sql.Timestamp;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.chrono.ChronoLocalDate;
import java.util.*;
import java.util.function.Function;
import java.util.function.Supplier;

public class EasyObj{

	public static String getClassSimpleName(@NonNull String className) {
		return className.substring(className.lastIndexOf('.')+1);
	}

	public static Object getValid(Object...arr){
		for(int i=0;i<arr.length;i++){
			if(isValid(arr[i]))
				return arr[i];
		}
		return null;
	}

	public static boolean isNumber(String value){
		return EasyMath.isNumeric(value);
	}

	public static String FormatNumber(BigDecimal value,int width,int decimalDigits){
		return EasyStr.bigDecimalToString(value,width,decimalDigits);
	}

	/** 表达式，如：a>=b */
	public static boolean expr(Comparable o1,@NonNull String expression,Comparable o2) {
		boolean result=false;
		if(o2==null && o1==null)
			result=false;
		else if(o2==null && o1!=null)
			result=true;
		else if(o1==null)
			result=false;
		else if(expression.equals(">"))
			result=o1.compareTo(o2)>0;
		else if(expression.equals("<"))
			result=o1.compareTo(o2)<0;
		else if(expression.equals(">="))
			result=o1.compareTo(o2)>=0;
		else if(expression.equals("="))
			result=o1.compareTo(o2)==0;
		else if(expression.equals("<="))
			result=o1.compareTo(o2)<=0;
		else if(expression.equals("!="))
			result=o1.compareTo(o2)!=0;
		return result;
	}

	/**小于或等于，即：<= */
	public static boolean lessEq(Comparable o1,Comparable o2) {
		boolean result=false;
		if(o1==null && o2==null)
			result=false;
		else if(o1==null && o2!=null)
			result=true;
		else if(o2==null)
			result=false;
		else
			result=o1.compareTo(o2)<=0;
		return result;
	}

	/**小于，即：< */
	public static boolean less(Comparable o1,Comparable o2) {
		boolean result=false;
		if(o1==null && o2==null)
			result=false;
		else if(o1==null && o2!=null)
			result=true;
		else if(o2==null)
			result=false;
		else
			result=o1.compareTo(o2)<0;
		return result;
	}

	/**大于，即：> */
	public static boolean more(Comparable o1,Comparable o2) {
		boolean result=false;
		if(o2==null && o1==null)
			result=false;
		else if(o2==null && o1!=null)
			result=true;
		else if(o1==null)
			result=false;
		else
			result=o1.compareTo(o2)>0;
		return result;
	}

	/**大于或等于，即：>= */
	public static boolean moreEq(Comparable o1,Comparable o2) {
		boolean result=false;
		if(o2==null && o1==null)
			result=false;
		else if(o2==null && o1!=null)
			result=true;
		else if(o1==null)
			result=false;
		else
			result=o1.compareTo(o2)>=0;
		return result;
	}

	public static boolean between(Comparable c,Comparable min,Comparable max) {
		return moreEq(c,min) && lessEq(c,max);
	}

	/**推荐使用*/
	public static boolean equal(Comparable o1,Comparable o2) {
		boolean result=false;
		if(o1==o2)
			result=true;
		else if(o2==null || o1==null)
			result=false;
		else
			result=o1.compareTo(o2)==0;
		return result;
	}


	public static int revserse(int comparedFlag){
		return -comparedFlag;
	}

	public static int compareTo(Object o1,Object o2,boolean revsersed){
		int result=compareTo(o1,o2);
		return revsersed?-result:result;
	}

	public static int compareTo(Object o1,Object o2){
		int result=2;
		if(o1==o2)
			result=0;
		else if(o1==null)
			result=-1;
		else if(o2==null)
			result=1;
		else if(o1.equals(o2))
			result=0;
		if(result==2){
			if(o1 instanceof Number&&o2 instanceof Number){
				result=esdk.math.compareTo((Number)o1,(Number)o2);
			}else if(o1 instanceof CharSequence&&o2 instanceof CharSequence){
				result=EasyStr.compareTo(o1.toString(),o2.toString());
			}else if(o1 instanceof LocalDateTime && o2 instanceof Date){
				result=esdk.time.toDate((LocalDateTime)o1).compareTo((Date)o2);
			}else if(o1 instanceof Date && o2 instanceof LocalDateTime){
				result=esdk.time.toLocalDate((Date)o1).compareTo(((LocalDateTime) o2).toLocalDate());
			}else if(o1 instanceof Boolean && o2 instanceof Number || o1 instanceof Number && o2 instanceof Boolean){
				result=esdk.obj.toBoolean(o1).compareTo(esdk.obj.toBoolean(o2));
			}else if(o1 instanceof Comparable c1 && o2 instanceof Comparable c2){
				if(o1.getClass().equals(o2.getClass()))
					result=c1.compareTo(c2);
				else if(o1.getClass().isAssignableFrom(o2.getClass())||o2.getClass().isAssignableFrom(o1.getClass()))
					result=c1.compareTo(c2);
				else
					result=esdk.str.valueOf(o1).compareTo(esdk.str.valueOf(o2));
			}else
				result=esdk.str.valueOf(o1).compareTo(esdk.str.valueOf(o2));
		}
		return result;
	}

	public static double min(double left,double right){
		return left<right?left:right;
	}

	public static int min(int left,int right){
		return left<right?left:right;
	}

	public static long max(long left,long right){
		return left>right?left:right;
	}
	public static double max(double left,double right){
		return left>right?left:right;
	}

	public static int max(int left,int right){
		return left>right?left:right;
	}

	/**注意：null不在比较之内*/
	public static <T extends Comparable>T max(T c1,T c2){
		if(c1==null)
  		return c2;
  	else if(c2==null)
  		return c1;
		return (T)(c1.compareTo(c2)>=0?c1:c2);
	}

	/**注意：null不在比较之内*/
	public static <T extends Comparable>T max(Collection<T> list){
		if(list.isEmpty())
			return null;
		T max=null;
		for(T item:list){
			if(max==null)
				max=item;
			else if(item!=null&&max!=null)
				max=item.compareTo(max)>0?item:max;
		}
		return (T)max;
	}
	/**注意：null不在比较之内*/
	public static <T extends Comparable>T min(Collection<T> list){
		if(list.isEmpty())
			return null;
		T min=null;
		for(T item:list){
			if(min==null)
				min=item;
			else if(item!=null&&min!=null)
				min=item.compareTo(min)<0?item:min;
		}
		return (T)min;
	}

	/**注意：null不在比较之内*/
	public static <T extends Comparable>T max(T...objs){
		if(objs.length==0)
			return null;
		T max=objs[0];
		for(T item:objs){
			if(item!=null)
				max=item.compareTo(max)>0?item:max;
		}
		return (T)max;
	}

	/**注意：null不在比较之内*/
	public static <T extends Comparable>T min(T...objs){
		if(objs.length==0)
			return null;
		T min=objs[0];
		for(T item:objs){
			if(item!=null)
				min=item.compareTo(min)<0?item:min;
		}
		return (T)min;
	}

	/**注意：null不在比较之内*/
	public static <T extends Comparable> T min(T c1,T c2){
		if(c1==null)
  		return c2;
  	else if(c2==null)
  		return c1;
		return (T)(c1.compareTo(c2)<=0?c1:c2);
	}

	public static boolean isNull(Object o){
		if(o==null)
			return true;
		return false;
	}

	/**其中一个有效就返回true*/
	public static boolean validOr(Object...v){
		if(v==null)
			return false;
		boolean result=false;
		for(int i=0;i<v.length;i++){
			result=result||isValid(v[i]);
			if(result)
				break;
		}
		return result;
	}

	/**全部有效就返回true*/
	public static boolean validAnd(Object...v) {
		return checkValid(v);
	}

	public static boolean checkValid(Object...v){
		if(v==null)
			return false;
		boolean result=true;
		for(int i=0;i<v.length;i++){
			result=result&&!isEmpty(v[i]);
			if(!result)
				break;
		}
		return result;
	}

	public static boolean checkValid(String...v){
		if(v==null)
			return false;
		boolean result=true;
		for(int i=0;i<v.length;i++){
			result=result&&!isBlank(v[i]);
		}
		return result;
	}

	public static boolean checkValid(Number...v){
		if(v==null)
			return false;
		boolean result=true;
		for(int i=0;i<v.length;i++){
			result=result&&!isBlank(v[i]);
		}
		return result;
	}

	public static boolean isValid(Object v){
		return !isEmpty(v);
	}

	public static boolean isValid(String v){
		return !isBlank(v);
	}

	public static boolean isValid(Number v){
		return !isBlank(v);
	}

	public static boolean isValid(Boolean v){
		return v!=null&&v.booleanValue();
	}

	public static boolean isBlank(String value){
		return value==null||value.isBlank();
	}

	/**
	 * 注意：为0时返回false
	 * */
	public static boolean isBlank(Number value){
		if(value==null)
			return true;
		return false;
	}

	/**
	 * 注意：null、""或为0时返回true
	 * */
	public static boolean isZero(Object value){
		if(value==null)
			return true;
		else if(value instanceof Number number)
			return number.doubleValue()==0.0;
		else
			return value.toString()=="";
	}

	public static boolean isNotZero(Object value){
		return !isZero(value);
	}

	/**
	 * 建议用在字符串、数字类型
	 * 注意：number为0时返回true
	 * */
	public static boolean isBlank(Object value){
		if(value==null)
			return true;
		if(value instanceof CharSequence cs)
			return cs.length()==0;
		else if(value instanceof Number)
			return isZero((Number)value);
		else if(value.getClass().isArray())
			return ((Object[])value).length==0;
		else if(value instanceof Collection collection)
			return collection.isEmpty();
		else if(value instanceof Map map)
			return map.isEmpty();
		else
			return value.toString().length()==0;
	}

	/**
	 * 建议用在数组、字符串
	 * 注意：number为0时返回false
	 * */
	public static boolean isEmpty(Object value){
		if(value==null)
			return true;
		if(value instanceof CharSequence)
			return ((CharSequence)value).length()==0;
		// else if(value instanceof Number number)
		// 	return value==null||number.doubleValue()==0.0;
		else if(value.getClass().isArray())
			return ((Object[])value).length==0;
		else if(value instanceof Collection collection)
			return collection.isEmpty();
		else if(value instanceof Map map)
			return map.isEmpty();
		else
			return value.toString().length()==0;
	}

	/**对象比较的最佳优化，避免了toJson的性能问题，也不会出现无限调用equals的错误*/
	public static boolean equals(Object o1,Object o2){
//		return Lang.equals(o1,o2); 比较对象: 支持数组，集合，和容器。请注意该方法会调用对象的.equals()的方法
		return eq(o1,o2);
	}

	public static boolean ne(Object o1, Object o2){
		return !eq(o1, o2);
	}

	/**对象比较的最佳优化，避免了toJson的性能问题，也不会出现无限调用equals的错误*/
	public static boolean eq(Object o1,Object o2){
		if (o1 == o2)
			return true;
		if (o1 == null && o2 == null)
			return true;
		if (o1 == null || o2 == null)
			return false;
		if (!o1.getClass().equals(o2.getClass())){
			if(o1 instanceof Number&&o2 instanceof Number)
				return o1.toString().equals(o2.toString());
			else
				return false;
		}
		if (o1 instanceof Boolean || o1 instanceof Number || o1 instanceof CharSequence)
			return o1.equals(o2);
		else if(o1 instanceof Date || o1 instanceof Time || o1 instanceof Timestamp || o1 instanceof LocalDateTime || o1 instanceof LocalTime)
			return o1.equals(o2);
		else if(o1.getClass().isPrimitive()&&o2.getClass().isPrimitive())
			return o1==o2;
		else if (o1.getClass().isArray())
			return Objects.deepEquals(o1,o2);
		else{ //这种bean、row类型的比较最耗时
			Method[] getterMethods=esdk.reflect.findGetterMethods(o1.getClass());
			try{
				for(Method m: getterMethods){
					Object v1=m.invoke(o1);
					Object v2=m.invoke(o2);
					if(!eq(v1,v2))
						return false;
				}
				return true;
			}catch(Exception e){
				throw esdk.tool.wrapThrowble(e);
			}
		}
	}

	/**注意：用于bean、pojo、row类的hashCode，如果是普通类不要调用这个方法，几十万就有可能会冲突，hashcode只是为了快速定位，不是唯一值，作为key的话一定要结合equals()使用*/
  public static int hashCode(Object o1) {
		if (o1==null) return 0;
		Method[] getterMethods=esdk.reflect.findGetterMethods(o1.getClass());
		CharAppender ca=new CharAppender(',');
		try{
			for(Method m:getterMethods){
				Object v1=m.invoke(o1);
				ca.append(m.getName()+":"+esdk.str.valueOf(v1));
			}
			return ca.toString().hashCode();
		}catch(Exception e){
			throw esdk.tool.wrapThrowble(e);
		}
  }

	/**
	 * 缺点：并不是加密级或工业级抗冲突哈希（比如 MurmurHash / xxHash）
	 * 如果你的数据量非常大（比如上千万 / 上亿条不同的字符串），仍然可能发生哈希冲突
	 * 如果你的场景是：几万 ~ 几百万级别的不同字符串，做缓存 key、分片、Map 存储等，这个方法完全够用！
	 * */
	public static long longHashCode(String value){
		long h=0;
		int off=0;
		char val[]=value.toCharArray();
		long len=value.length();
		for(int i=0;i<len;i++){
			h=31*h+val[off++];
		}
		return h;
	}

	/**生成千万级别不重复的long值*/
	public static long longHashCode(Object value){
		Object simplifiedValue=unikey(value);
		if(simplifiedValue instanceof Integer || simplifiedValue instanceof Long||simplifiedValue instanceof Short)
			return (long)simplifiedValue;
		else
			return longHashCode(simplifiedValue.toString());
	}

	/**
	 * 生成唯一值，但会返回简单类型(number或string)，以解决hashcode不唯一的问题，如果要限制长度，就建议用longHashCode(unikey(v))
	 * */
	public static Serializable unikey(Object obj) {
		if(obj==null) return 0;
		else if(obj instanceof Integer || obj instanceof Long||obj instanceof Short)
			return (Serializable)obj;
		else if(obj instanceof Double || obj instanceof Float || obj instanceof BigDecimal)
			return obj.toString();
		else if(obj instanceof Date || obj instanceof Time || obj instanceof LocalDateTime || obj instanceof LocalTime)
			return obj.toString();
		else if(obj instanceof List list){
			if(list.isEmpty()) return 0;
			if(list.size()==1) return unikey(list.getFirst());
			return esdk.str.listToStr(list);
		}else if(obj instanceof Object[] arr){
			if(arr.length==0) return 0;
			if(arr.length==1) return unikey(arr[0]);
			return esdk.array.toStr(arr);
		}else{
			return esdk.str.valueOf(obj);
		}
	}

	public static boolean isEnglish(char value){
		return((value>='A'&&value<='Z')||(value>='a'&&value<='z'));
	}

	public static boolean isNumeric(char value){
		return(value>='0'&&value<='9');
	}

	public static <T> T convert(Object fromObj,Class<T> toCls){
		return (T)convert(null, fromObj, toCls);
	}

	/**简单版的类型转换，复杂的用esdk.obj.valueOf()*/
	public static Object convert(Object keyName ,Object fromObj,Class toCls){
		if(toCls==null&&fromObj==null)
			return null;
		else if(toCls.isPrimitive())
			return valueOfPrimitive(toCls,fromObj);
		else if(fromObj==null || fromObj instanceof String && fromObj.toString().equals(""))
			return null;
		else if(fromObj!=null&&fromObj.getClass().equals(toCls))
			return fromObj;
		Object result=null;
		try{
			if(toCls.equals(String.class))
				result=esdk.str.valueOf(fromObj);
			else if(toCls.equals(Boolean.class) ||toCls.equals(boolean.class) )
				result=isTrue(fromObj);
			else if(esdk.tool.asSubClass(toCls,Number.class)){
				result=EasyMath.convert(fromObj,toCls);
			}else if(esdk.tool.asSubClass(toCls,Date.class)) {
				if(fromObj instanceof LocalDateTime){
					result=esdk.time.toDate((LocalDateTime)fromObj);
				}else if(fromObj instanceof Date)
					result=fromObj;
				else{
					long time=esdk.time.valueOf((String)fromObj).getTime();
					Constructor c=toCls.getConstructor(long.class);
					result=c.newInstance(time);
				}
			}
			else if(toCls.equals(Time.class)) {
				if(fromObj instanceof Time)
					return fromObj;
				else
					result=esdk.time.toTime(fromObj.toString());
			}
			else if(toCls.equals(LocalDateTime.class) && fromObj instanceof String){
				result=esdk.time.toLocalDateTime(fromObj.toString());
			}else{
				Constructor c=toCls.getConstructor(fromObj.getClass());
				result=c.newInstance(fromObj);
			}
		}catch(Exception e){
			throw new ParseRuntimeException(e.toString()+": class:"+toCls.getName()+",value:"+fromObj+((keyName==null)?"":(",key:"+keyName)));
		}
		return result;
	}

	/**调用nutz的casTo*/
	public static <C> C castTo(Object srcObj,Class<C> toCls) {
		return Castors.me().castTo(srcObj,toCls);
	}

	/**效果与nutz的castTo一样，性能会比nutz要好一些*/
	public static <C> C valueOf(Class<C> toCls,Object fromObj){
		try{
			if(toCls==null||fromObj==null)
				return (C)fromObj;
			if(fromObj.getClass().equals(toCls))
				return (C)fromObj;
			else if(toCls.isPrimitive())
				return valueOfPrimitive(toCls,fromObj);
			else if(fromObj instanceof Date){
				if(toCls.equals(java.sql.Timestamp.class))
					return (C)new java.sql.Timestamp(((Date)fromObj).getTime());
				else if(toCls.equals(java.sql.Date.class))
					return (C)new java.sql.Date(((Date)fromObj).getTime());
				else if(toCls.equals(java.util.Date.class))
					return (C)new java.util.Date(((Date)fromObj).getTime());
				else if(toCls.equals(LocalDateTime.class))
					return (C)esdk.time.toLocalDateTime((Date)fromObj);
				else if(toCls.equals(LocalDate.class))
					return (C)esdk.time.toLocalDate((Date)fromObj);
				else{
					Constructor c=toCls.getConstructor(new Class[]{
						long.class
					});
					return (C)c.newInstance(new Object[]{((Date)fromObj).getTime()});
				}
			}
			else if(esdk.tool.asSubClass(toCls,Date.class)){
				if(fromObj instanceof LocalDateTime){
					return (C)esdk.time.toDate((LocalDateTime)fromObj);
				}
				else if(fromObj instanceof LocalDate){
					return (C)esdk.time.toDate((LocalDate)fromObj);
				}
			}
			else if(toCls.equals(Integer.class))
				return (C)esdk.math.toInteger(fromObj);
			else if(toCls.equals(Double.class))
				return (C)esdk.math.toDouble(fromObj);
			else if(toCls.equals(BigDecimal.class))
				return (C)esdk.math.toBigDecimal(fromObj);
			else if(toCls.equals(Long.class))
				return (C)esdk.math.toLong(fromObj);
			else if(toCls.equals(Short.class))
				return (C)esdk.math.toShort(fromObj);
			else if(toCls.equals(BigDecimal.class))
				return (C)esdk.math.toLong(fromObj);
			else if((toCls.equals(Boolean.class))&&EasyStr.existOf(new String[]{
					"1","是","Y","yes","true"
			},fromObj.toString()))
				return (C)Boolean.TRUE;
			else if((toCls.equals(Boolean.class))&&EasyStr.existOf(new String[]{
					"0","否","N","no","false"
			},fromObj.toString()))
				return (C)Boolean.FALSE;
			else if(toCls.equals(Timestamp.class)&&fromObj instanceof String)
				return (C)Timestamp.valueOf((String)fromObj);
			else if(toCls.equals(java.sql.Date.class)&&fromObj instanceof String)
				return (C)java.sql.Date.valueOf((String)fromObj);
			else if(toCls.equals(Date.class)&& fromObj instanceof String)
				return (C)EasyTime.valueOf((String)fromObj);
			else if(toCls.equals(Date.class)&&fromObj instanceof String)
				return (C)EasyTime.valueOf((String)fromObj);
			else if(toCls.isArray() && fromObj instanceof String) {
				String clsName=toCls.toString();
				if(clsName.contains("String"))
					return (C)esdk.str.splits((String)fromObj);
				if(clsName.contains("Long"))
					return (C)esdk.math.toLongArray((String)fromObj);
				else if(clsName.contains("Integer"))
					return (C)esdk.math.toInteger((String)fromObj);
				else if(clsName.contains("Double"))
					return (C)esdk.math.toDouble((String)fromObj);
				else if(clsName.contains("BigDecimal"))
					return (C)esdk.math.toBigDecimalArray(esdk.str.splits((String)fromObj));
			}
			return Castors.me().castTo(fromObj,toCls);
		}catch(Exception e){
			throw new ParseRuntimeException(e.toString()+". 值["+fromObj+"]无法转换为类型["+toCls.getName()+"]");
		}
	}

	public static <C>C valueOfPrimitive(Class<C> cls,Object value){
		if(value==null)
			value="0";
		String s=value.toString();
		if(s.length()==0)
			s="0";
		if(cls.equals(short.class))
			return (C)Short.valueOf(s);
		else if(cls.equals(int.class))
			return (C)Integer.valueOf(s);
		else if(cls.equals(long.class))
			return (C)Long.valueOf(s);
		else if(cls.equals(double.class))
			return (C)Double.valueOf(s);
		else if(cls.equals(boolean.class)){
			return (C)Boolean.valueOf(isTrue(s));
		}else
			throw new ParseRuntimeException("无法转换值["+value+"]为类型["+cls.getName()+"]");
	}

	public static boolean isFalse(Object value){
		return !isTrue(value);
	}

	public static boolean isTrue(Object value){
		if(value==null)
			return false;
		else if(value instanceof Boolean)
			return (Boolean)value;
		else if(value instanceof Number n)
			return n.intValue()>0;
		else if(value instanceof String s)
			return isTrue(s);
		else if(value instanceof byte[] b)
			return b[0]==1;
		else
			return false;
	}

	public static boolean and(Object...v){
		if(v==null)
			return false;
		boolean result=true;
		for(int i=0;result&&i<v.length;i++){
			result=result&&v[i]!=null;
			if(v[i] instanceof Boolean)
				result=result&&(Boolean)v[i];
			else if(v[i] instanceof Number)
				result=result&&((Number)v[i]).doubleValue()!=0d;
		}
		return result;
	}

	public static <T,R> R IFNotnull(T obj,Func<T,R> trueVal){
		try{
			if(obj!=null)
				return trueVal.invoke(obj);
			else
				return null;
		}catch(Exception e){
			throw esdk.tool.wrapThrowble(e);
		}
	}

	public static <T,R> R IFNotnull(T obj,Func<T,R> trueVal,R otherVal){
		try{
			if(obj!=null)
				return trueVal.invoke(obj);
			else
				return otherVal;
		}catch(Exception e){
			throw esdk.tool.wrapThrowble(e);
		}
	}

	/**Null的N是大写，因为java区分不了函数和值*/
	public static <T,R> R IFNotNull(T obj,Func<T,R> trueVal,Func<T,R> falseVal){
		try{
			if(obj!=null)
				return trueVal.invoke(obj);
			else
				return falseVal.invoke(obj);
		}catch(Exception e){
			throw esdk.tool.wrapThrowble(e);
		}
	}

	public static <R> R IF(boolean ifTrue,R trueVal,R falseVal){
		return ifTrue?trueVal:falseVal;
	}

	public static <R> R IF(boolean ifTrue,FuncNoArg<R> trueVal,R other){
		try{
			if(ifTrue)
				return trueVal.invoke();
			return (R)other;
		}catch(Exception e){
			throw esdk.tool.wrapThrowble(e);
		}
	}

	public static <R> R IF(boolean ifTrue,FuncNoArg<R> trueVal,FuncNoArg<R> falseVal){
		try{
			if(ifTrue)
				return trueVal.invoke();
			else if(falseVal!=null)
				return falseVal.invoke();
			else
				return null;
		}catch(Exception e){
			throw esdk.tool.wrapThrowble(e);
		}
	}

	/**为空则返回默认值，跟or用法一样*/
	public static <R> R ifNull(R value,R def){
		return value!=null?value:def;
	}

	/**
	 * 类似于js的obj?.key?.subKey的使用方式，如果抛异常返回默认值或null
	 * */
	public static <R> R GET(Supplier<R> fn,R... others){
		try{
			return fn.get();
		}catch(NullPointerException | IndexOutOfBoundsException | NoSuchElementException e){
			return or(others);
		}catch(Exception e){
			throw esdk.tool.wrapThrowble(e);
		}
	}

	/** 相当于js的||*/
	public static <R> R or(R...vars){
		for(R var:vars){
			if(var!=null){
				return var;
			}
		}
		return null;
	}

	/**第1个参数不需要用函数*/
	public static <R> R or(R p1,FuncNoArg<R>... others){
		if(p1!=null)
			return p1;
		else{
			for(FuncNoArg func:others){
        R v;
        try{
          v=(R)func.invoke();
        }catch(Exception e){
          throw esdk.tool.wrapThrowble(e);
        }
        if(v!=null)
					return v;
			}
		}
		return null;
	}

	/**忽略下标越界的异常，之前的方法名是firstNonNull //TODO 要问一下泽鑫用在哪里*/
	public static <R> R OR(FuncNoArg<R>... fns){
		R r = null;
		for (FuncNoArg<R> fn : fns) {
			try{
				if((r = fn.invoke()) != null) break;
			}catch (NullPointerException | IndexOutOfBoundsException | NoSuchElementException ignored){
			}catch (Exception e0){
				throw esdk.tool.wrapThrowble(e0);
			}
		}
		return r;
	}


	public static String or(String...vars){
		return EasyStr.or(vars);
	}

	public static boolean or(Boolean...vars){
		for(int i=0;i<vars.length;i++){
			if(EasyObj.isTrue(vars[i]))
				return true;
		}
		return false;
	}

	public static boolean and(Boolean...vars){
		for(int i=0;i<vars.length;i++){
			if(EasyObj.isFalse(vars[i]))
				return false;
		}
		return true;
	}

	public static boolean isTrue(String value){
		if(value==null)
			return false;
		return value.matches("1|Y|y|yes|YES|true|TRUE|YES|T|是");
	}

	/**判断是否可转换为boolean值
	 * ignoreEmpty：为true时空值返回true*/
	public static boolean isBoolean(String value,boolean ignoreEmpty){
		if(ignoreEmpty&&isBlank(value))
			return true;
		return value.matches("1|Y|y|yes|YES|true|TRUE|YES|T|是|0|N|y|no|NO|false|FALSE|F|否");
	}

	/**判断是否可转换为boolean值,注意空值返回false*/
	public static boolean isBoolean(String value){
		if(isBlank(value))
			return false;
		return value.matches("1|Y|y|yes|YES|true|TRUE|YES|T|是|0|N|y|no|NO|false|FALSE|F|否");
	}

	public static String toJson(Object o) {
		if(o==null)
			return null;
		return JsonUtils.stringify(o);
	}

	public static <T> List<T> toList(String jsonarrayStr,Class<T> c) {
  	if(jsonarrayStr==null)
			return null;
  	return JsonUtils.toBeanList(jsonarrayStr,c);
  }

	public static <T> List<T> toList(@NonNull Enumeration<T> e) {
		List result=new LinkedList<T>();
		while(e.hasMoreElements()){
			result.add(e.nextElement());
		}
		return result;
	}

	public static <T> T toBean(String jsonobjectStr,Class<T> c) {
  	if(jsonobjectStr==null)
			return null;
  	else
  		return JsonUtils.toBean(jsonobjectStr,c);
  }

  /**通用的对象比较函数，通过json字串比较对象是否相同，不存在循环调用Object.equals(obj)的问题*/
  public static boolean equalsByJson(Object o1,Object o2) {
  	if(o1==o2)
  		return true;
  	else if(o1==null||o2==null)
  		return false;
  	else if(o1.getClass().equals(o2.getClass()))
  		return JsonUtils.stringify(o1).equals(JsonUtils.stringify(o2));
  	return false;
  }

	/**二维数组转换为List*/
	public static List<List> arr2ToList(@NonNull Object[][] arr2){
		List result=new ArrayList(arr2.length);
		for(Object[] item:arr2) {
			result.add(Arrays.asList(item));
		}
		return result;
	}

	/**List转换为二维数组*/
	public static Object[][] listToArr2(@NonNull Collection<Collection> list){
		int rowcount=list.size();
		if(rowcount<=0)
			return new Object[0][];
		Object[][] result=new Object[rowcount][];
		int i=0;
		for(Iterator iter=list.iterator();iter.hasNext();){
			Object object=(Object)iter.next();
			Object[] array=null;
			if(object instanceof List){
				array=((List)object).toArray();
			}else if(object instanceof String){
				array=new String[]{
					(String)object
				};
			}else if(object instanceof String[]){
				array=(String[])object;
			}else if(object instanceof Object[]){
				array=(Object[])object;
			}else if(object instanceof Object){
				array=new Object[]{
					object
				};
			}else{
				array=new Object[0];
			}
			result[i++]=array;
		}
		return result;
	}

	public static Boolean toBoolean(Object value){
		if(value==null || value.toString().length()==0)
			return null;
		else
			return isTrue(value);
	}

	public static <T>T trim(T obj) {
		if(obj==null) return null;
		else if(obj instanceof CharSequence)
			return (T)esdk.str.trim((CharSequence)obj);
		else if(obj instanceof Map)
			return (T)esdk.map.trim((Map)obj);
		else if(obj instanceof Collection<?>){
			for(Object item:(Collection<?>)obj){
				trim(item); //只能替换pojo或map对象
			}
			return obj;
		}
		else if(obj.getClass().isArray()){
			Object[] objArr=(Object[])obj;
			for(int i=0,n=objArr.length;i<n;i++){
				objArr[i]=trim(objArr[i]);
			}
			return obj;
		}
		else if(EasyBean.isPojo(obj)){
			return EasyBean.trim(obj);
		}
		else
			return obj;
  }

	/**TODO 泽鑫加上注释*/
	public static <T> void validExecute(T obj, Callback<T> func){
		if(validAnd(obj)){
			func.invoke(obj);
		}
	}

	/**
	 * func无论出任何异常或返回空都会忽视并返回默认值
	 */
	public static <R> R orElse(@NonNull FuncNoArg<R> func, R defVal){
    try{
			R res=func.invoke();
			return res == null ? defVal : res;
		}catch(Throwable e){
			return defVal;
    }
  }

	/**
	 * func无论出任何异常或返回空都会忽视并调用supplier获取默认值，原则上supplier不应该抛出任何异常
	 */
	public static <R> R orElse(@NonNull FuncNoArg<R> func, @NonNull Supplier<R> supplier){
		try{
			R res=func.invoke();
			return res == null ? supplier.get() : res;
		}catch(Throwable e){
			return supplier.get();
		}
	}

	public static int byte2int(byte b){
		return b & 0xFF;
	}
}
